﻿using System.Globalization;
using NPack.Interfaces;

namespace NPack
{
    #region License

    // Copyright 2007-2008 Rory Plaire (codekaizen@gmail.com)
    /*
     * This license governs use of the accompanying software. If you use the software, you
     * accept this license. If you do not accept the license, do not use the software.
     *
     * 1. Definitions
     * The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
     * same meaning here as under U.S. copyright law.
     * A "contribution" is the original software, or any additions or changes to the software.
     * A "contributor" is any person that distributes its contribution under this license.
     * "Licensed patents" are a contributor's patent claims that read directly on its contribution.
     *
     * 2. Grant of Rights
     * (A) Copyright Grant- Subject to the terms of this license, including the license conditions
     *     and limitations in section 3, each contributor grants you a non-exclusive, worldwide,
     *     royalty-free copyright license to reproduce its contribution, prepare derivative works
     *     of its contribution, and distribute its contribution or any derivative works that you create.
     * (B) Patent Grant- Subject to the terms of this license, including the license conditions and
     *     limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free
     *     license under its licensed patents to make, have made, use, sell, offer for sale, import,
     *     and/or otherwise dispose of its contribution in the software or derivative works of the
     *     contribution in the software.
     *
     * 3. Conditions and Limitations
     * (A) No Trademark License- This license does not grant you rights to use any contributors'
     *     name, logo, or trademarks.
     * (B) If you bring a patent claim against any contributor over patents that you claim are
     *     infringed by the software, your patent license from such contributor to the software
     *     ends automatically.
     * (C) If you distribute any portion of the software, you must retain all copyright, patent,
     *     trademark, and attribution notices that are present in the software.
     * (D) If you distribute any portion of the software in source code form, you may do so only under
     *     this license by including a complete copy of this license with your distribution. If you
     *     distribute any portion of the software in compiled or object code form, you may only do so
     *     under a license that complies with this license.
     * (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no
     *     express warranties, guarantees or conditions. You may have additional consumer rights under
     *     your local laws which this license cannot change. To the extent permitted under your local laws,
     *     the contributors exclude the implied warranties of merchantability, fitness for a particular
     *     purpose and non-infringement.
     *
     */

    #endregion License

    using System;

    namespace NPack
    {
        /// <summary>
        /// A matrix component or matrix element which represents a
        /// <see cref="System.Double"/>.
        /// </summary>
        /// <remarks>
        /// Use this structure as the type parameter for <see cref="IMatrix{T}"/> when you want
        /// a matrix of Double values, since it implements <see cref="IComputable{T}"/>, which
        /// allows numerical operations on value types.
        /// </remarks>
        [Serializable]
        public struct DecimalComponent : IEquatable<DecimalComponent>,
                                         IComparable<DecimalComponent>,
                                         IPrecisable<DecimalComponent>,
                                         IComputable<Decimal, DecimalComponent>,
                                         IEquatable<Decimal>,
                                         IComparable<Decimal>,
                                         IComputable<Decimal>,
                                         IConvertible,
                                         IFormattable
        {
            private Decimal _value;

            ///<summary>
            /// Creates a new <see cref="NPack.DecimalComponent"/> converting from the given <paramref name="value"/>.
            ///</summary>
            ///<param name="value">The Decimal used to set the DecimalComponent value.</param>
            public DecimalComponent(Decimal value)
            {
                _value = value;
            }

            ///<summary>
            /// Creates a new <see cref="NPack.DecimalComponent"/> converting from the given <paramref name="value"/>.
            ///</summary>
            ///<param name="value">The double used to set the DecimalComponent value.</param>
            public DecimalComponent(Double value)
                : this(new Decimal(value))
            {
            }

            ///<summary>
            /// Creates a new <see cref="NPack.DecimalComponent"/> converting from the given <paramref name="value"/>.
            ///</summary>
            ///<param name="value">The Sinlge used to set the DecimalComponent value.</param>
            public DecimalComponent(Single value)
                : this((Decimal)value)
            {
            }

            /// <summary>
            /// Returns the sum of the Object and <paramref name="b"/>.
            /// It must not modify the value of the Object.
            /// </summary>
            /// <param name="b">The second operand.</param>
            /// <returns>The sum.</returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Add(decimal b)
            {
                return new DecimalComponent(_value + b);
            }

            /// <summary>
            /// Returns the difference of the Object and <paramref name="b"/>.
            /// It must not modify the value of the Object.
            /// </summary>
            /// <param name="b">The second operand.</param>
            /// <returns>The difference.</returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Subtract(decimal b)
            {
                return new DecimalComponent(_value - b);
            }

            /// <summary>
            /// Returns the product of the Object and <paramref name="b"/>.
            /// It must not modify the value of the Object.
            /// </summary>
            /// <param name="b">The factor to multiply by.</param>
            /// <returns>The product.</returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Multiply(decimal b)
            {
                return new DecimalComponent(_value * b);
            }

            /// <summary>
            /// Returns the quotient of the Object and <paramref name="b"/>.
            /// It must not modify the value of the Object.
            /// </summary>
            /// <param name="b">The second operand.</param>
            /// <returns>The quotient.</returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Divide(decimal b)
            {
                return new DecimalComponent(_value / b);
            }

            /// <summary>
            /// Sets the value of the IComputable value.
            /// </summary>
            /// <param name="value">Value used to set the IComputable.</param>
            /// <returns>The value of the IComputable converted from <paramref name="value"/>.</returns>
            public DecimalComponent Set(decimal value)
            {
                _value = value;
                return this;
            }

            /// <summary>
            /// Returns String representation of this value.
            /// </summary>
            /// <returns>A formatted String displaying this value.</returns>
            public override String ToString()
            {
                return _value.ToString(CultureInfo.InvariantCulture);
            }

            /// <summary>
            /// Generates a hash code for the DecimalComponent value.
            /// </summary>
            /// <returns>A value to represent this value in a hash table.</returns>
            public override Int32 GetHashCode()
            {
                return _value.GetHashCode();
            }

            /// <summary>
            /// Implicitly converts a Double value to a DecimalComponent.
            /// </summary>
            /// <param name="value">Value to convert.</param>
            /// <returns>
            /// A DecimalComponent set to <paramref name="value"/>.
            /// </returns>
            public static implicit operator DecimalComponent(Double value)
            {
                return new DecimalComponent(value);
            }

            /// <summary>
            /// Implicitly converts a Decimal value to a DecimalComponent.
            /// </summary>
            /// <param name="value">Value to convert.</param>
            /// <returns>
            /// A DecimalComponent set to <paramref name="value"/>.
            /// </returns>
            public static implicit operator DecimalComponent(Decimal value)
            {
                return new DecimalComponent(value);
            }

            /// <summary>
            /// Explicitly converts a DecimalComponent to a Decimal.
            /// </summary>
            /// <param name="component">DecimalComponent to convert.</param>
            /// <returns>
            /// Value of type Decimal with the same value as the DecimalComponent.
            /// </returns>
            public static explicit operator Decimal(DecimalComponent component)
            {
                return component._value;
            }

            /// <summary>
            /// Adds a DecimalComponent and a Decimal.
            /// </summary>
            /// <param name="lhs">Left hand of the addition operation.</param>
            /// <param name="rhs">Right hand of the addition operation.</param>
            /// <returns>
            /// The sum of <paramref name="lhs"/> and <paramref name="rhs"/>.
            /// </returns>
            public static Decimal operator +(DecimalComponent lhs, Decimal rhs)
            {
                return lhs._value + rhs;
            }

            /// <summary>
            /// Subtracts a Decimal from a DecimalComponent.
            /// </summary>
            /// <param name="lhs">Left hand of the subtraction operation.</param>
            /// <param name="rhs">Right hand of the subtraction operation.</param>
            /// <returns>
            /// The difference of <paramref name="lhs"/> and <paramref name="rhs"/>.
            /// </returns>
            public static Decimal operator -(DecimalComponent lhs, Decimal rhs)
            {
                return lhs._value - rhs;
            }

            #region IEquatable<DecimalComponent> Members

            /// <summary>
            /// Evaluates equality of two DecimalComponent instances.
            /// </summary>
            /// <param name="other">The DecimalComponent to compare to.</param>
            /// <returns>
            /// True if the two DecimalComponent instances are equal; false otherwise.
            /// </returns>
            public Boolean Equals(DecimalComponent other)
            {
                return _value == other._value;
            }

            #endregion IEquatable<DecimalComponent> Members

            #region IComparable<DecimalComponent> Members

            /// <summary>
            /// Compares two DecimalComponent instances.
            /// </summary>
            /// <param name="other">The DecimalComponent to compare to.</param>
            /// <returns>
            /// 0 if they are equal,
            /// 1 if the called-on instance is greater,
            /// -1 if <paramref name="other"/> is greater.
            /// </returns>
            public Int32 CompareTo(DecimalComponent other)
            {
                return _value.CompareTo(other._value);
            }

            #endregion IComparable<DecimalComponent> Members

            #region IAddable<DecimalComponent> Members

            /// <summary>
            /// Adds two DecimalComponent values.
            /// </summary>
            /// <param name="a">The other addend.</param>
            /// <returns>
            /// The sum of this DecimalComponent and <paramref name="a"/>.
            /// </returns>
            public DecimalComponent Add(DecimalComponent a)
            {
                return new DecimalComponent(_value + a._value);
            }

            #endregion IAddable<DecimalComponent> Members

            #region ISubtractable<DecimalComponent> Members

            /// <summary>
            /// Subtracts two DecimalComponent values.
            /// </summary>
            /// <param name="a">The subtrahend.</param>
            /// <returns>
            /// The difference of this DecimalComponent (minuend) and
            /// <paramref name="a"/>.
            /// </returns>
            public DecimalComponent Subtract(DecimalComponent a)
            {
                return new DecimalComponent(_value - a._value);
            }

            #endregion ISubtractable<DecimalComponent> Members

            #region IHasZero<DecimalComponent> Members

            /// <summary>
            /// Returns the zero value for a DecimalComponent. Equal to 0.
            /// </summary>
            public DecimalComponent Zero
            {
                get { return new DecimalComponent(Decimal.Zero); }
            }

            #endregion IHasZero<DecimalComponent> Members

            #region INegatable<DecimalComponent> Members

            /// <summary>
            /// Returns the negation of the DecimalComponent value. Also the
            /// additive inverse.
            /// </summary>
            /// <remarks>
            /// The value returns solves the following equation:
            /// <code>
            /// DecimalComponent a = 5, b = a.Negative();
            ///
            /// Assert.IsTrue(a.Add(b).Equals(0));
            /// </code>
            /// </remarks>
            /// <returns>The negated DecimalComponent.</returns>
            public DecimalComponent Negative()
            {
                return new DecimalComponent(-_value);
            }

            #endregion INegatable<DecimalComponent> Members

            #region IMultipliable<DecimalComponent> Members

            /// <summary>
            /// Multiplies two DecimalComponents and returns the product.
            /// </summary>
            /// <param name="a">The multiplier.</param>
            /// <returns>
            /// The product of the DecimalComponent instance and
            /// <paramref name="a"/>.
            /// </returns>
            public DecimalComponent Multiply(DecimalComponent a)
            {
                return new DecimalComponent(_value * a._value);
            }

            #endregion IMultipliable<DecimalComponent> Members

            #region IDivisible<DecimalComponent> Members

            /// <summary>
            /// Divides two DecimalComponent instances and returns the quotient.
            /// </summary>
            /// <param name="a">The divisor.</param>
            /// <returns>
            /// The quotient of dividing the DecimalComponent instance
            /// (the dividend) and <paramref name="a"/>.
            /// </returns>
            public DecimalComponent Divide(DecimalComponent a)
            {
                return new DecimalComponent(_value / a._value);
            }

            #endregion IDivisible<DecimalComponent> Members

            #region IHasOne<DecimalComponent> Members

            /// <summary>
            /// Returns the multiplicative identity.
            /// </summary>
            public DecimalComponent One
            {
                get { return new DecimalComponent(1d); }
            }

            #endregion IHasOne<DecimalComponent> Members

            #region IEquatable<Decimal> Members

            /// <summary>
            /// Evaluates equality of a DecimalComponent instance and a Decimal value.
            /// </summary>
            /// <param name="other">The Decimal value to compare to.</param>
            /// <returns>
            /// True if the two DecimalComponent instances are equal; false otherwise.
            /// </returns>
            public Boolean Equals(Decimal other)
            {
                return _value == other;
            }

            #endregion IEquatable<Decimal> Members

            #region IComparable<Decimal> Members

            /// <summary>
            /// Compares a DecimalComponent instance and a Decimal value.
            /// </summary>
            /// <param name="other">The Decimal value to compare to.</param>
            /// <returns>
            /// 0 if they are equal,
            /// 1 if the DecimalComponent instance is greater,
            /// -1 if <paramref name="other"/> is greater.
            /// </returns>
            public Int32 CompareTo(Decimal other)
            {
                return _value.CompareTo(other);
            }

            #endregion IComparable<Decimal> Members

            #region IAddable<Decimal> Members

            /// <summary>
            /// Adds a DecimalComponent value and a Decimal.
            /// </summary>
            /// <param name="a">The other addend.</param>
            /// <returns>
            /// The sum of this DecimalComponent and <paramref name="a"/>.
            /// </returns>
            Decimal IAddable<Decimal>.Add(Decimal a)
            {
                return _value + a;
            }

            #endregion IAddable<Decimal> Members

            #region ISubtractable<Decimal> Members

            /// <summary>
            /// Subtracts a Decimal value from the DecimalComponent value.
            /// </summary>
            /// <param name="a">The subtrahend.</param>
            /// <returns>
            /// The difference of this DecimalComponent (minuend) and
            /// <paramref name="a"/>.
            /// </returns>
            Decimal ISubtractable<Decimal>.Subtract(Decimal a)
            {
                return _value - a;
            }

            #endregion ISubtractable<Decimal> Members

            #region IHasZero<Decimal> Members

            /// <summary>
            /// Gets the additive identity as a Decimal: 0F.
            /// </summary>
            Decimal IHasZero<Decimal>.Zero
            {
                get { return Decimal.Zero; }
            }

            #endregion IHasZero<Decimal> Members

            #region INegatable<Decimal> Members

            /// <summary>
            /// Returns the negation of the DecimalComponent value as a Double. Also the
            /// additive inverse.
            /// </summary>
            /// <remarks>
            /// The value returns solves the following equation:
            /// <code>
            /// DecimalComponent a = 5, b = a.Negative();
            ///
            /// Assert.IsTrue(a.Add(b).Equals(0));
            /// </code>
            /// </remarks>
            /// <returns>The negated DecimalComponent as a Double.</returns>
            Decimal INegatable<Decimal>.Negative()
            {
                return -_value;
            }

            #endregion INegatable<Decimal> Members

            #region IMultipliable<Decimal> Members

            /// <summary>
            /// Multiplies the DecimalComponent with Double and returns the product.
            /// </summary>
            /// <param name="a">The multiplier.</param>
            /// <returns>
            /// The product of the DecimalComponent instance and
            /// <paramref name="a"/>.
            /// </returns>
            Decimal IMultipliable<Decimal>.Multiply(Decimal a)
            {
                return _value * a;
            }

            #endregion IMultipliable<Decimal> Members

            #region IDivisible<Double> Members

            /// <summary>
            /// Divides the DecimalComponent by a Double and returns the quotient.
            /// </summary>
            /// <param name="a">The divisor.</param>
            /// <returns>
            /// The quotient of dividing the DecimalComponent instance
            /// (the dividend) and <paramref name="a"/>.
            /// </returns>
            Decimal IDivisible<Decimal>.Divide(Decimal a)
            {
                return _value / a;
            }

            #endregion IDivisible<Double> Members

            #region IHasOne<Decimal> Members

            /// <summary>
            /// Gets the multiplicative identity as a Double: 1F.
            /// </summary>
            Decimal IHasOne<Decimal>.One
            {
                get { return Decimal.One; }
            }

            #endregion IHasOne<Decimal> Members

            #region IBooleanComparable<DecimalComponent> Members

            /// <summary>
            /// Evaluates if the DecimalComponent instance is greater than
            /// the given value.
            /// </summary>
            /// <param name="value">The value to compare to.</param>
            /// <returns>True if the DecimalComponent instance is greater
            /// than <paramref name="value"/>; false otherwise.</returns>
            public Boolean GreaterThan(DecimalComponent value)
            {
                return _value > value._value;
            }

            /// <summary>
            /// Evaluates if the DecimalComponent instance is greater than
            /// or equal to the given value.
            /// </summary>
            /// <param name="value">The value to compare to.</param>
            /// <returns>
            /// True if the DecimalComponent instance is greater
            /// than or equal to <paramref name="value"/>; false otherwise.
            /// </returns>
            public Boolean GreaterThanOrEqualTo(DecimalComponent value)
            {
                return _value >= value._value;
            }

            /// <summary>
            /// Evaluates if the DecimalComponent instance is less than
            /// the given value.
            /// </summary>
            /// <param name="value">The value to compare to.</param>
            /// <returns>True if the DecimalComponent instance is less
            /// than <paramref name="value"/>; false otherwise.</returns>
            public Boolean LessThan(DecimalComponent value)
            {
                return _value < value._value;
            }

            /// <summary>
            /// Evaluates if the DecimalComponent instance is less than
            /// or equal to the given value.
            /// </summary>
            /// <param name="value">The value to compare to.</param>
            /// <returns>
            /// True if the DecimalComponent instance is less
            /// than or equal to <paramref name="value"/>; false otherwise.
            /// </returns>
            public Boolean LessThanOrEqualTo(DecimalComponent value)
            {
                return _value <= value._value;
            }

            #endregion IBooleanComparable<DecimalComponent> Members

            #region IBooleanComparable<Double> Members

            /// <summary>
            /// Evaluates if the DecimalComponent instance is greater than
            /// the given Double value.
            /// </summary>
            /// <param name="value">The value to compare to.</param>
            /// <returns>True if the DecimalComponent instance is greater
            /// than <paramref name="value"/>; false otherwise.</returns>
            public Boolean GreaterThan(Decimal value)
            {
                return _value > value;
            }

            /// <summary>
            /// Evaluates if the DecimalComponent instance is greater than
            /// or equal to the given Decimal value.
            /// </summary>
            /// <param name="value">The value to compare to.</param>
            /// <returns>
            /// True if the DecimalComponent instance is greater
            /// than or equal to <paramref name="value"/>; false otherwise.
            /// </returns>
            public Boolean GreaterThanOrEqualTo(Decimal value)
            {
                return _value >= value;
            }

            /// <summary>
            /// Evaluates if the DecimalComponent instance is less than
            /// the given Decimal value.
            /// </summary>
            /// <param name="value">The value to compare to.</param>
            /// <returns>True if the DecimalComponent instance is less
            /// than <paramref name="value"/>; false otherwise.</returns>
            public Boolean LessThan(Decimal value)
            {
                return _value < value;
            }

            /// <summary>
            /// Evaluates if the DecimalComponent instance is less than
            /// or equal to the given Decimal value.
            /// </summary>
            /// <param name="value">The value to compare to.</param>
            /// <returns>
            /// True if the DecimalComponent instance is less
            /// than or equal to <paramref name="value"/>; false otherwise.
            /// </returns>
            public Boolean LessThanOrEqualTo(Decimal value)
            {
                return _value <= value;
            }

            #endregion IBooleanComparable<Double> Members

            #region IExponential<DecimalComponent> Members

            /// <summary>
            /// Raises the DecimalComponent value to the given exponent.
            /// <paramref name="power"/>.
            /// </summary>
            /// <param name="power">
            /// The value of the exponent.
            /// </param>
            /// <returns>
            /// The value of the DecimalComponent (the base)
            /// raised to the given power.
            /// </returns>
            public DecimalComponent Power(Double power)
            {
                throw new NotSupportedException();
            }

            /// <summary>
            /// Computes the value of the square root of the DecimalComponent.
            /// </summary>
            /// <returns>
            /// The value of the square root of the DecimalComponent.
            /// </returns>
            public DecimalComponent Sqrt()
            {
                throw new NotSupportedException();
            }

            /// <summary>
            /// Computes the log of the DecimalComponent in the
            /// <paramref name="newBase">given base</paramref>.
            /// </summary>
            /// <param name="newBase">The base to compute the log in.</param>
            /// <returns>
            /// The log of the DecimalComponent in the new base given.
            /// </returns>
            public DecimalComponent Log(Double newBase)
            {
                throw new NotSupportedException();
            }

            /// <summary>
            /// Computes the log of the DecimalComponent in base e.
            /// </summary>
            /// <returns>The natural log of the DecimalComponent.</returns>
            public DecimalComponent Log()
            {
                throw new NotSupportedException();
            }

            /// <summary>
            /// Computes e to the power of the DecimalComponent.
            /// </summary>
            /// <returns>
            /// The natural log base, e, raised to the power
            /// of the value of the DecimalComponent.
            /// </returns>
            public DecimalComponent Exp()
            {
                throw new NotSupportedException();
            }

            #endregion IExponential<DecimalComponent> Members

            #region IExponential<Decimal> Members

            /// <summary>
            /// Raises the DecimalComponent value to the given
            /// exponent, returned as a Decimal.
            /// <paramref name="power"/>.
            /// </summary>
            /// <param name="power">
            /// The value of the exponent.
            /// </param>
            /// <returns>
            /// The value of the DecimalComponent (the base)
            /// raised to the given power.
            /// </returns>
            Decimal IExponential<Decimal>.Power(Double power)
            {
                throw new NotSupportedException();
            }

            /// <summary>
            /// Computes the value of the square root of the DecimalComponent,
            /// returned as a Decimal.
            /// </summary>
            /// <returns>
            /// The value of the square root of the DecimalComponent.
            /// </returns>
            Decimal IExponential<Decimal>.Sqrt()
            {
                throw new NotSupportedException();
            }

            Decimal IExponential<Decimal>.Log(Double newBase)
            {
                throw new NotSupportedException();
            }

            /// <summary>
            /// Computes the log of the DecimalComponent in base 10,
            /// returned as a Decimal.
            /// </summary>
            /// <returns>
            /// The log of the DecimalComponent in the new base given.
            /// </returns>
            Decimal IExponential<Decimal>.Log()
            {
                throw new NotSupportedException();
            }

            /// <summary>
            /// Computes the log of the DecimalComponent in base e,
            /// returned as a Decimal.
            /// </summary>
            /// <returns>The natural log of the DecimalComponent.</returns>
            Decimal IExponential<Decimal>.Exp()
            {
                throw new NotSupportedException();
            }

            #endregion IExponential<Decimal> Members

            #region IComputable<DecimalComponent> Members

            /// <summary>
            /// Computes the absolute value of the DecimalComponent.
            /// </summary>
            /// <returns>
            /// The absolute value of the DecimalComponent's value.
            /// </returns>
            public DecimalComponent Abs()
            {
                return new DecimalComponent(System.Math.Abs(_value));
            }

            /// <summary>
            /// Sets the value of the DecimalComponent.
            /// </summary>
            /// <param name="value">
            /// The value to set the DecimalComponent to, cast to a Decimal.
            /// </param>
            /// <returns>
            /// A DecimalComponent with the given <paramref name="value"/>.
            /// </returns>
            public DecimalComponent Set(Double value)
            {
                _value = new Decimal(value);
                return this;
            }

            #endregion IComputable<DecimalComponent> Members

            #region IComputable<Decimal> Members

            /// <summary>
            /// Computes the absolute value of the DecimalComponent,
            /// returned as a Decimal.
            /// </summary>
            /// <returns>
            /// The absolute value of the DecimalComponent's value.
            /// </returns>
            Decimal IComputable<Decimal>.Abs()
            {
                return System.Math.Abs(_value);
            }

            /// <summary>
            /// Computes the absolute value of the DecimalComponent,
            /// returned as a Decimal.
            /// </summary>
            /// <returns>
            /// The absolute value of the DecimalComponent's value.
            /// </returns>
            Decimal IComputable<Decimal>.Set(Double value)
            {
                _value = new Decimal(value);
                return _value;
            }

            #endregion IComputable<Decimal> Members

            #region IConvertible Members

            /// <summary>
            /// Gets the TypeCode value for the DecimalComponent.
            /// </summary>
            /// <returns><see cref="TypeCode.Decimal"/></returns>
            public TypeCode GetTypeCode()
            {
                return TypeCode.Decimal;
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="Boolean"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="Boolean"/>.</returns>
            public Boolean ToBoolean(IFormatProvider provider)
            {
                return Convert.ToBoolean(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="Byte"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="Byte"/>.</returns>
            public Byte ToByte(IFormatProvider provider)
            {
                return Convert.ToByte(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="Char"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="Char"/>.</returns>
            public Char ToChar(IFormatProvider provider)
            {
                return Convert.ToChar(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="DateTime"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="DateTime"/>.</returns>
            public DateTime ToDateTime(IFormatProvider provider)
            {
                return Convert.ToDateTime(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="Decimal"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="Decimal"/>.</returns>
            public Decimal ToDecimal(IFormatProvider provider)
            {
                return _value;
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="Double"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="Double"/>.</returns>
            public Double ToDouble(IFormatProvider provider)
            {
                return Convert.ToDouble(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="Int16"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="Int16"/>.</returns>
            public Int16 ToInt16(IFormatProvider provider)
            {
                return Convert.ToInt16(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="Int32"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="Int32"/>.</returns>
            public Int32 ToInt32(IFormatProvider provider)
            {
                return Convert.ToInt32(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="Int64"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="Int64"/>.</returns>
            public Int64 ToInt64(IFormatProvider provider)
            {
                return Convert.ToInt64(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="SByte"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="SByte"/>.</returns>
            [CLSCompliant(false)]
            public SByte ToSByte(IFormatProvider provider)
            {
                return Convert.ToSByte(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="Single"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="Single"/>.</returns>
            public Single ToSingle(IFormatProvider provider)
            {
                return Convert.ToSingle(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="String"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="String"/>.</returns>
            public String ToString(IFormatProvider provider)
            {
                return Convert.ToString(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a value of the given type.
            /// </summary>
            /// <param name="conversionType">
            /// Type to convert to.
            /// </param>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>
            /// The DecimalComponent as a value of <paramref name="conversionType"/>.
            /// </returns>
            public Object ToType(Type conversionType, IFormatProvider provider)
            {
                return Convert.ChangeType(_value, conversionType, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="UInt16"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="UInt16"/>.</returns>
            [CLSCompliant(false)]
            public UInt16 ToUInt16(IFormatProvider provider)
            {
                return Convert.ToUInt16(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="UInt32"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="UInt32"/>.</returns>
            [CLSCompliant(false)]
            public UInt32 ToUInt32(IFormatProvider provider)
            {
                return Convert.ToUInt32(_value, provider);
            }

            /// <summary>
            /// Converts the DecimalComponent to a <see cref="UInt64"/> value.
            /// </summary>
            /// <param name="provider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help convert the DecimalComponent value.
            /// </param>
            /// <returns>The DecimalComponent as a <see cref="UInt64"/>.</returns>
            [CLSCompliant(false)]
            public UInt64 ToUInt64(IFormatProvider provider)
            {
                return Convert.ToUInt64(_value, provider);
            }

            #endregion IConvertible Members

            #region IFormattable Members

            /// <summary>
            /// Generates a String representation of the DecimalComponent.
            /// </summary>
            /// <param name="format">The format String to use in formatting.</param>
            /// <param name="formatProvider">
            /// An <see cref="IFormatProvider"/> instance used to
            /// help format the DecimalComponent value.
            /// </param>
            /// <returns>
            /// A formatted String which represents the DecimalComponent value.
            /// </returns>
            public String ToString(String format, IFormatProvider formatProvider)
            {
                return _value.ToString(format, formatProvider);
            }

            #endregion IFormattable Members

            /// <summary>
            /// Returns the sum of the Object and <paramref name="b"/>.
            /// It must not modify the value of the Object.
            /// </summary>
            /// <param name="b">The second operand.</param>
            /// <returns>The sum.</returns>
            public DecimalComponent Add(Double b)
            {
                return new DecimalComponent(_value + new Decimal(b));
            }

            /// <summary>
            /// Returns the quotient of the Object and <paramref name="b"/>.
            /// It must not modify the value of the Object.
            /// </summary>
            /// <param name="b">The second operand.</param>
            /// <returns>The quotient.</returns>
            public DecimalComponent Divide(Double b)
            {
                return new DecimalComponent(_value / new Decimal(b));
            }

            /// <summary>
            /// Returns the product of the Object and <paramref name="b"/>.
            /// It must not modify the value of the Object.
            /// </summary>
            /// <param name="b">The factor to multiply by.</param>
            /// <returns>The product.</returns>
            public DecimalComponent Multiply(Double b)
            {
                return new DecimalComponent(_value * new Decimal(b));
            }

            /// <summary>
            /// Returns the difference of the Object and <paramref name="b"/>.
            /// It must not modify the value of the Object.
            /// </summary>
            /// <param name="b">The second operand.</param>
            /// <returns>The difference.</returns>
            public DecimalComponent Subtract(Double b)
            {
                return new DecimalComponent(_value - new Decimal(b));
            }

            #region Implementation of IHasOneHalf<out DecimalComponent>

            /// <summary>
            /// Gets the 0.5 or 1/2 as TComponent
            /// </summary>
            public DecimalComponent OneHalf
            {
                get { return new DecimalComponent(new Decimal(0.5d));}
            }

            #endregion

            #region Implementation of IRoundable<DecimalComponent>

            /// <summary>
            /// Gets
            /// </summary>
            /// <returns></returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Floor()
            {
                return new DecimalComponent(Decimal.Floor(_value));
            }

            /// <summary>
            ///
            /// </summary>
            /// <param name="nearest"></param>
            /// <returns></returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent FloorNearest(int nearest)
            {
                return new DecimalComponent(Decimal.Floor(_value / nearest) * nearest);
            }

            /// <summary>
            ///
            /// </summary>
            /// <returns></returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Ceiling()
            {
                return new DecimalComponent(Decimal.Ceiling(_value));
            }

            /// <summary>
            ///
            /// </summary>
            /// <param name="nearest"></param>
            /// <returns></returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent CeilingNearest(int nearest)
            {
                return new DecimalComponent(Decimal.Ceiling(_value / nearest) * nearest);
            }

            /// <summary>
            ///
            /// </summary>
            /// <returns></returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Round()
            {
                return Round(0, RoundingMode.Default);
            }

            /// <summary>
            ///
            /// </summary>
            /// <param name="mode"></param>
            /// <returns></returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Round(RoundingMode mode)
            {
                return Round(0, mode);
            }

            /// <summary>
            ///
            /// </summary>
            /// <param name="decimals"></param>
            /// <returns></returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Round(int decimals)
            {
                return Round(decimals, RoundingMode.Default);
            }

            /// <summary>
            ///
            /// </summary>
            /// <param name="decimals"></param>
            /// <param name="mode"></param>
            /// <returns></returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent Round(int decimals, RoundingMode mode)
            {
                switch (mode)
                {
                    case RoundingMode.MidPointRoundingToEven:
                    case RoundingMode.MidpointRoundingAwayFromZero:
                        return new DecimalComponent(Decimal.Round(_value, decimals, (MidpointRounding)mode));
                    case RoundingMode.JavaRint:
                        return new DecimalComponent(Decimal.Floor(_value / decimals + new Decimal(0.5d)));
                }
                throw new ArgumentOutOfRangeException("mode");
            }

            #endregion

            #region Implementation of IPrecisable<DecimalComponent>

            /// <summary>
            /// Returns an precised instance or value
            /// </summary>
            /// <param name="precisionMode"></param>
            /// <returns></returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent MakePrecise(PrecisionMode precisionMode)
            {
                return MakePrecise(precisionMode, RoundingMode.Default, 0);
            }

            /// <summary>
            /// Returns an precised instance or value
            /// </summary>
            /// <param name="precisionMode">The precision mode</param>
            ///<param name="roundingMode">The rounding mode</param>
            /// <returns>The precised value</returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent MakePrecise(PrecisionMode precisionMode, RoundingMode roundingMode)
            {
                return MakePrecise(precisionMode, roundingMode, 0);
            }

            /// <summary>
            /// Returns an precised instance or value
            /// </summary>
            /// <param name="precisionMode">The precision mode</param>
            ///<param name="decimals">The number of decimals</param>
            /// <returns>The precised value</returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent MakePrecise(PrecisionMode precisionMode, int decimals)
            {
                return MakePrecise(precisionMode, RoundingMode.Default, decimals);
            }

            /// <summary>
            /// Returns an precised instance or value
            /// </summary>
            /// <param name="precisionMode">The precision mode</param>
            ///<param name="roundingMode">The rounding mode</param>
            ///<param name="decimals">The number of decimals</param>
            /// <returns>The precised value</returns>
#if DOTNET40
            [System.Diagnostics.Contracts.Pure]
#endif
            public DecimalComponent MakePrecise(PrecisionMode precisionMode, RoundingMode roundingMode, int decimals)
            {
                switch (precisionMode)
                {
                    case PrecisionMode.ToDecimal:
                        return this;
                    case PrecisionMode.ToDouble:
                        return new DecimalComponent((Double)_value);
                    case PrecisionMode.ToSingle:
                        return new DecimalComponent((Single)_value);
                    case PrecisionMode.ToFixed:
                        return Round(decimals, roundingMode);
                }
                throw new ArgumentOutOfRangeException("precisionMode");
            }

            #endregion
        }
    }
}